﻿using System;
using System.Text;

namespace SSHAgent
{
    class Program
    {
        static void Main(string[] args)
        {

            if (args.Length == 0)
            {
                Console.Write("[ssh-agent]# ");
                Console.WriteLine("无效参数,例：root@127.0.0.1:22  -m3306:3306");
                return;
            }
            if (!CMD.TryParseFirstArg(args[0], out var sshHost, out var sshUser, out int sshPort))
            {
                Console.Write("[ssh-agent]# ");
                Console.WriteLine("无效参数,例：root@127.0.0.1:22  -m3306:3306");
                return;
            }
            SSHAgent ssHAgent = null;
            var hasP = CMD.IsPassword(args, out string pwd);
            while (true)
            {
                string sshPwd = null;
                if (hasP)
                { 
                    sshPwd = pwd;
                    hasP = false;
                }
                else
                {
                    Console.Write("[ssh-agent]# 请输入密码：");
                    sshPwd = CMD.ReadLinePassword();
                }
               
                ssHAgent = new SSHAgent(sshHost, sshPwd, sshUser, sshPort);
                if (!ssHAgent.Connect(out string msg))
                {
                    Console.Write("[ssh-agent]# ");
                    Console.WriteLine(msg);
                    continue;
                }
                else
                {
                    ssHAgent.OnClose += SsHAgent_OnClose;
                    break;
                }

            }

            for (int i = 1; i < args.Length; i++)
            {
                if (CMD.IsMapper(args[i], out uint remotePort, out uint localPort))
                {
                    ssHAgent.Agent(remotePort, localPort);
                    Console.Write("[ssh-agent]# ");
                    Console.WriteLine($"映射成功:{localPort}->{remotePort}");
                }
            }
            while (true)
            {
                Console.Write("[ssh-agent]# ");
                string arg = Console.ReadLine();
                if (string.IsNullOrEmpty(arg)) continue;
                if (CMD.IsExit(arg))
                {
                    Console.Write("exit:");
                    return;
                }
                if (CMD.IsMapper(arg, out uint remotePort, out uint localPort))
                {
                    ssHAgent.Agent(remotePort, localPort);
                    Console.Write("[ssh-agent]# ");
                    Console.WriteLine($"映射成功:{localPort}->{remotePort}");
                }
            }

        }

        private static void SsHAgent_OnClose()
        {
            Console.WriteLine("连接断开");
            Environment.Exit(0);
        }

        public class CMD
        {
            public static string ReadLinePassword()
            {
                StringBuilder sb = new StringBuilder();

                while (true)
                {

                    ConsoleKeyInfo cki = Console.ReadKey(true);
                    if (cki.Key == ConsoleKey.Enter || cki.Key == ConsoleKey.Escape)
                    {
                        Console.WriteLine();
                        break;
                    }
                    if (cki.Key == ConsoleKey.Backspace)
                    {
                        if (sb.Length > 0)
                        {

                            Console.Write("\b \b");
                            sb.Length--;
                        }
                        continue;
                    }
                    Console.Write('*');
                    sb.Append(cki.KeyChar);
                }
                return sb.ToString();
            }
            public static bool TryParseFirstArg(string arg, out string host, out string user, out int port)
            {
                port = 22;
                user = null;
                host = null;
                var args = arg.Split("@");

                if (args.Length != 2)
                {
                    return false;
                }
                user = args[0];
                var ports = args[1].Split(":");
                host = ports[0];
                if (ports.Length == 2)
                {
                    if (!int.TryParse(ports[1], out port))
                    {
                        return false;
                    }
                }
                return true;
            }

            public static bool IsExit(string arg)
            {
                return arg.Equals("exit");
            }

            public static bool IsPassword(string[] args, out string password)
            {
                password = null;
                foreach (var arg in args)
                {
                    if (arg.StartsWith("-p"))
                    {
                        password = arg.Substring(2);
                        return true;
                    }
                }
                return false;
            }

            public static bool IsMapper(string arg, out uint remotePort, out uint localPort)
            {
                remotePort = 3306;
                localPort = 3306;
                if (arg.StartsWith("-m"))
                {
                    var ports = arg.Substring(2).Split(":");
                    if (ports.Length == 2)
                    {
                        if (!uint.TryParse(ports[0], out localPort))
                        {
                            Console.Write("[ssh-agent]# ");
                            Console.WriteLine("无效的端口号");
                            return false;
                        }
                        if (!uint.TryParse(ports[1], out remotePort))
                        {
                            Console.Write("[ssh-agent]# ");
                            Console.WriteLine("无效的端口号");
                            return false;
                        }
                        return true;
                    }
                    else if (ports.Length == 1)
                    {
                        if (!uint.TryParse(ports[0], out localPort))
                        {
                            Console.Write("[ssh-agent]# ");
                            Console.WriteLine("无效的端口号");
                            return false;
                        }
                        remotePort = localPort;
                        return true;
                    }
                    else
                    {
                        Console.Write("[ssh-agent]# ");
                        Console.WriteLine("无效的端口号");
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }
    }
}
